﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Diagnostics;
using System.Threading;


namespace TLSC.utils
{

    /// <summary>
    /// 自定义串口操作类
    /// 
    /// </summary>
    public class MySerialPort
    {
        /// <summary>
        /// 释放资源
        /// </summary>

        /// <summary>
        /// 私有串口
        /// </summary>
        private SerialPort myPort;
        //BackgroundWorker bk = new BackgroundWorker();

        /// <summary>
        /// 接收时线程休眠时间，默认30毫秒
        /// </summary>
        public int SleepValue
        {
            get
            {
                return sleepValue;
            }
            set
            {
                sleepValue = value;
            }
        }

        private int sleepValue = 30;

        /// <summary>
        /// 构造函数,用于没有返回值的单向命令
        /// </summary>
        /// <param name="serialPort">经过实例化的串口,未实例化则在此构造函数中初始化默认值 com1 9600</param>
        public MySerialPort(SerialPort serialPort)
        {
            if (serialPort == null)
            {
                myPort = new SerialPort("COM1", 9600);
                //this.receiveDataLen = 0;
            }
            else
            {
                this.myPort = serialPort;
                //this.receiveDataLen = 0;
            }
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="serialPort">经过实例化的串口,未实例化则在此构造函数中初始化默认值 com1 9600</param>
        /// <param name="receiveDataLen">欲接收数据的长度</param>
        public MySerialPort(SerialPort serialPort, int receiveDataLen)
        {
            if (serialPort == null)
            {
                myPort = new SerialPort("COM1", 9600);
                this.ReceiveDataLen = receiveDataLen;
            }
            else
            {
                this.myPort = serialPort;
                this.ReceiveDataLen = receiveDataLen;
            }

            //bk.DoWork += new DoWorkEventHandler(bk_DoWork);
            //bk.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bk_RunWorkerCompleted);

        }

        /// <summary>
        /// 测量超时时间
        /// </summary>
        private Stopwatch stopwatch = new Stopwatch();

        /// <summary>
        /// 需接收数据的长度
        /// </summary>
        public int ReceiveDataLen { get; set; }

        /// <summary>
        /// 此计算机的串口号
        /// </summary>
        public static IList<string> GetPortNames
        {
            get
            {


                IList<string> tmp = new List<string>();

                tmp = SerialPort.GetPortNames().ToList();

                if (tmp.Count < 1)
                    tmp.Add("None");

                return tmp;
            }
        }

        /// <summary>
        /// 接受数据用的字节数组
        /// </summary>
        private byte[] receiveedData = new byte[0];

        /// <summary>
        /// 打开串口
        /// </summary>
        public void Open()
        {
            if (!myPort.IsOpen)
                myPort.Open();
        }

        /// <summary>
        /// 关闭串口.(guanbi)
        /// </summary>
        //public void Close()
        //{
        //    //if (myPort.IsOpen)
        //    //    myPort.Close();

        //}

        /// <summary>
        /// 向串口写数据,并返回接到的数据，超时时间 由初始化的 串口ReadTimeout 决定
        /// </summary>
        /// <param name="writeData"></param>
        public byte[] Wirte(byte[] writeData)
        {
            try
            {

                Open();

                lock (myPort)
                {


                    myPort.Write(writeData, 0, writeData.Length);

                    //重新计时
                    stopwatch.Reset();

                    //重新计时开始
                    stopwatch.Start();

                    //清空接收缓冲区数据
                    myPort.DiscardInBuffer();

                    //开始循环
                    while (true)
                    {
                        //串口数据接收较慢，等待若干毫秒，提高cpu利用率
                        Thread.Sleep(100);
                        myPortDataReceived();

                        if (receiveedData.Length >= ReceiveDataLen && receiveedData.Length > 0)
                        {
                            break;

                        }

                        if (stopwatch.ElapsedMilliseconds > myPort.ReadTimeout)
                        {
                            //Close();

                            throw new TimeoutException("在等待时间内没有应答，连接超时");
                        }

                    }
                    return this.receiveedData;
                }

            }
            catch (Exception ex)
            {
                throw ex;

            }
            finally
            {
                //this.buttonTestConnect.Enabled = true;
                Array.Resize(ref receiveedData, 0);
                stopwatch.Stop();
                //myPort.Dispose();
            }


        }
        //int i = 0;
        /// <summary>
        /// 接收串口数据
        /// </summary>
        private void myPortDataReceived()
        {
            //i++;
            //mye.I = i;// receiveedData.Length;

            mye.I = receiveedData.Length;
            if (MyUpEvent != null)
                MyUpEvent(this, mye);

            if (myPort.BytesToRead > 0)
            {
                stopwatch.Reset();

                stopwatch.Start();

                int oldLen = receiveedData.Length;

                var tmpbyte = new byte[myPort.BytesToRead];

                //myPort.Read(tmpbyte, 0, myPort.BytesToRead);
                myPort.Read(tmpbyte, 0, tmpbyte.Length);

                int newLen = oldLen + tmpbyte.Length;

                Array.Resize(ref receiveedData, newLen);

                tmpbyte.CopyTo(receiveedData, oldLen);
            }


        }

        /// <summary>
        /// 向串口写数据,无返回数据
        /// </summary>
        /// <param name="writeData"></param>
        public void WirteNoReturn(byte[] writeData)
        {
            Open();
            myPort.Write(writeData, 0, writeData.Length);

        }

        public delegate void MyUpDelegate(object sender, MyUpEventArgs e);

        public event MyUpDelegate MyUpEvent;

        MyUpEventArgs mye = new MyUpEventArgs();

    }
    /// <summary>
    /// 用于返回接收数据的长度，参数有整形的I
    /// </summary>
    public class MyUpEventArgs : EventArgs
    {
        public MyUpEventArgs(int i)
        {
            this.I = i;
        }

        public MyUpEventArgs()
        {
            // TODO: Complete member initialization
        }
        public int I;
    }
}
